#ifndef __MQ_LOGGER_HPP__
#define __MQ_LOGGER_HPP__
#include <cstdio>
#include <ctime>

// 封装一个日志宏，通过日志宏进行日志的打印，在打印的信息前带有系统时间以及文件名和行号
// [日志等级][时:分:秒 文件名:行号] 信息
namespace imq {
    #define DBG 0
    #define INF 1
    #define ERR 2
    #define DEFAULT_LOG_LEVEL DBG

    // 这里的do while 是为了能使用break，没有循环效果
    // __VA_ARGS__是一个预处理标识符，用于表示可变参数宏中的可变参数部分，只能在使用...定义的可变参数宏中使用
    // 当可变参数部分为空时，__VA_ARGS__被替换为空字符串，但可能会保留前面的逗号，这种情况会导致编译错误
    // ##是预处理器的连接运算符，它的作用是：拼接两个符号
    // ##__VA_ARGS__中##的特殊作用：(1)当__VA_ARGS__为空时，会被替换为空字符串，自动删除前面的逗号和__VA_ARGS__，避免产生语法错误。
    //                             (2)当可变参数不为空时，与__VA_ARGS__作用一样
    #define LOG(level_str, log_level, format, ...)                                                             \
        do                                                                                                     \
        {                                                                                                      \
            if (log_level < DEFAULT_LOG_LEVEL)                                                                 \
                break;                                                                                         \
            time_t t = time(nullptr);                                                                          \
            struct tm *ltm = localtime(&t);                                                                    \
            char tmp[32] = {0};                                                                                \
            strftime(tmp, 31, "%H:%M:%S", ltm);                                                                \
            fprintf(stdout, "[%s][%s %s:%d] " format "\n", level_str, tmp, __FILE__, __LINE__, ##__VA_ARGS__); \
        } while (0)

    #define DLOG(format, ...) LOG("DEBUG", DBG, format, ##__VA_ARGS__);
    #define ILOG(format, ...) LOG("INFO ", DBG, format, ##__VA_ARGS__);
    #define ELOG(format, ...) LOG("ERROR", DBG, format, ##__VA_ARGS__);
}

#endif